package com.guet.careapp.controller.rest.controller.service;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.guet.careapp.controller.rest.common.errorCode.Error;
import com.guet.careapp.controller.rest.common.errorCode.ErrorCode;
import com.guet.careapp.controller.rest.common.errorCode.ErrorCodeFactory;
import com.guet.careapp.pojo.*;
import com.guet.careapp.pojo.rest.AjaxReturn;
import com.guet.careapp.pojo.rest.Introduction;
import com.guet.careapp.service.*;
import com.guet.careapp.utils.ConvertUtils;
import com.guet.careapp.utils.TimeHelper;

import java.math.BigInteger;
import java.util.*;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

import org.apache.commons.collections.map.HashedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

/**
 * Created by LXM on 2017/10/15.
 *
 * @author LXM
 * @version 1.0
 * @description 用于提供位置服务的类
 * @datetime 12:11
 */
@Controller
@Path("/services/location")
public class Location {

    protected Logger logger = LoggerFactory.getLogger(Location.class);

    @Autowired
    private IInstructionService instructionService;

    @Autowired
    private IUserGuardianInfoService guardianInfoService;


    @Autowired
    private IUserUnderGuardiansInfoService underGuardiansInfoService;

    @Autowired
    private IPositionService positionService;

    @Autowired
    private IPushService pushService;

    @Autowired
    private IUserInfoService userInfoService;

    private Gson gson = new GsonBuilder().setPrettyPrinting().create();

    /**
     * POST 方法.
     * 监护人获取被监护人的位置的方法，监护人发送一条指令给服务器，服务器发送给RabbitMQ，
     * 客户端上线后自己从RabbitMQ中读取这条Message，经过解析后执行Message附带的查询位置指令（已协商）。
     * 日志需要记录本次指令。
     *
     * @param introduction 传入一条指令
     * @return 返回码
     */
    @POST
    @Path("/ug")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public String askforUgLocation(Introduction introduction) {

        Map<String, Object> map = new HashMap<>();
        TUserGuardianInfo guardian;
        TUserUnderGuardiansInfo underGuardians;
        Integer g;
        Integer ug;
        //取出参数
        try {
            g = Integer.parseInt(introduction.getSendUid());
            ug = Integer.parseInt(introduction.getReceiveUid());
        } catch (Exception e) {
            return gsonStr(Error.TypeError);
        }
        //查询用户是否存在
        try {
            guardian = guardianInfoService.findById(g);
            underGuardians = underGuardiansInfoService.findById(ug);

            if (guardian == null || underGuardians == null) {
                return gsonStr(Error.NotFond);
            }
        } catch (Exception e) {
            return gsonStr(Error.Unkonwn);
        }
        //保存指令
        Map para = (HashMap) introduction.getContent();
        TInstruction i = new TInstruction();
        i.setExcuation(0);
        i.setGInfoId(guardian);
        i.setUgInfoId(underGuardians);
        i.setPara(new Gson().toJson(para));
        i.setCreateTime(TimeHelper.getTime());
        try {
            instructionService.save(i);
        } catch (Exception e) {
            return gsonStr(Error.Unkonwn);
        }

        logger.info("开始推送请求位置的信息");
        //向极光推送发送这条信息
        Error error = pushService.PushLocationRequest(introduction, underGuardians.getTUserInfo().getDeviceId());

        return gsonStr(error);

    }


    /**
     * POST 方法,发送监护人位置.
     * 被监护人上线之后，通过百度SDK寻找自己的位置。获取位置后，调用此API，提供一个坐标的json，
     * 发送到RabbitMQ上，监护人上线的时候，从此处监听到消息队列中有未处理的消息，下载这条信息，
     * 去解析这条带指令的位置信息。从而得知被监护人的位置。
     * 位置需要写入数据库位置表中。日志需要记录本次指令。
     *
     * @param introduction 指令
     * @return 返回码
     */

    @POST
    @Path("/g")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public String sendLocation(Introduction introduction) {

        Map<String, Object> map = new HashMap<>();
        TUserGuardianInfo guardian;
        TUserUnderGuardiansInfo underGuardians;
        Integer g;
        Integer ug;
        //取出参数
        try {
            ug = Integer.parseInt(introduction.getSendUid());
            g = Integer.parseInt(introduction.getReceiveUid());
        } catch (Exception e) {
            return gsonStr(Error.TypeError);
        }
        //查询用户是否存在
        try {
            guardian = guardianInfoService.findById(g);
            underGuardians = underGuardiansInfoService.findById(ug);

            if (guardian == null || underGuardians == null) {
                return gsonStr(Error.NotFond);
            }
        } catch (Exception e) {
            return gsonStr(Error.Unkonwn);
        }
        //保存指令
        Map para = (HashMap) introduction.getContent();
        TInstruction i = new TInstruction();
        i.setExcuation(0);
        i.setGInfoId(guardian);
        i.setUgInfoId(underGuardians);
        i.setPara(new Gson().toJson(para));
        i.setCreateTime(TimeHelper.getTime());
        try {
            instructionService.save(i);
        } catch (Exception e) {
            return gsonStr(Error.Unkonwn);
        }
        //保存被监护人当前位置
        TServicePosition position = new TServicePosition();
        Map contentMap = (Map) introduction.getContent();
        position.setPosition(ConvertUtils.map2String(contentMap));
        position.setTime(TimeHelper.getTime());
        position.setUserInfoId(underGuardians.getTUserInfo());
        try {
            positionService.save(position);
        } catch (Exception e) {
            logger.error("服务器保存被监护人位置信息异常");
            return gsonStr(Error.Unkonwn);
        }
        logger.info("开始回应请求位置的信息");
        //向极光推送发送这条信息
        Error error = pushService.PushLocationResponse(introduction, guardian.getTUserInfo().getDeviceId());

        return gsonStr(error);

    }


    /**
     * GET 方法,查询数据库中，被监护人的历史位置.
     *
     * @return 历史数据的JSON
     */
    @GET
    @Path("/history")
    @Produces(MediaType.APPLICATION_JSON)
    public String getHistory(
            @QueryParam("u_id") final String UGid
    ) {

        List<TServicePosition> positionList;
        int i = 0;
        List<Map> list = new ArrayList<>();

        Map<String, Object> fieldMap = new HashMap<>();
        fieldMap.put("user_info_id", UGid);
        positionList = positionService.findAllByField(fieldMap);
        if (positionList.size() == 0) {
            return gsonStr(Error.NotFond);
        }
        Collections.sort(positionList, new Comparator<TServicePosition>() {
            @Override
            public int compare(TServicePosition o1, TServicePosition o2) {
                return -o1.getTime().compareTo(o2.getTime());
            }
        });
        for (TServicePosition p : positionList) {
            i++;
            fieldMap = new HashMap<>();
            fieldMap.put("id", i);
            fieldMap.put("u_id", p.getUserInfoId().getUId());
            fieldMap.put("username", p.getUserInfoId().getName());
            fieldMap.put("position", p.getPosition());
            fieldMap.put("time", p.getTime());
            list.add(fieldMap);
            if (i > 101)
                break;
        }

        return gsonObj(Error.Success, list);
    }


    /**
     * .
     * Delete 方法,删除被监护人的历史信息数据.
     *
     * @return 返回码
     * @ ugid 被监护人的ID
     */
    @DELETE
    @Path("/history")
    @Produces(MediaType.APPLICATION_JSON)
    public String deleteHistory(String json) {

        Map map = ConvertUtils.jsonToMap(json);
        try {
            positionService.deleteById(Integer.parseInt("" + map.get("uid")));
        } catch (Exception e) {
            return gsonStr(Error.Unkonwn);
        }
        return gsonStr(Error.Success);

    }


    private String gsonStr(Error error) {
        ErrorCode errorCode = ErrorCodeFactory.get(error);
        return gson.toJson(new AjaxReturn(errorCode.getCodeNum(), errorCode.getMeanning()));
    }

    private String gsonObj(Error error, Object object) {
        ErrorCode errorCode = ErrorCodeFactory.get(error);
        return gson.toJson(new AjaxReturn(errorCode.getCodeNum(), errorCode.getMeanning(), object));
    }


    /**
     * 保存自定义的信息，不做转发
     *
     * @param json
     * @return
     */
    @POST
    @Path("/custom")
    @Produces(MediaType.APPLICATION_JSON)
    public String saveLocationWithoutForward(String json) {

        Map map = ConvertUtils.jsonToMap(json);
        Integer u_id = 0;
        String pos;
        Long time;
        TUserInfo userInfo;
        try {
            u_id = Integer.parseInt((String) map.get("u_id"));
            pos = (String) map.get("pos");
            time = Long.parseLong((String) map.get("time"));
            userInfo = userInfoService.findById(u_id);
            if (u_id == null) {
                logger.error("用户不存在，无法保存自定义的位置信息");
                return gsonStr(Error.NotFond);
            }

        } catch (Exception e) {
            logger.error("自定义保存位置异常");
            e.printStackTrace();
            return gsonStr(Error.TypeError);
        }
        TServicePosition position = new TServicePosition();
        position.setPosition(pos);
        position.setTime(BigInteger.valueOf(time));
        position.setUserInfoId(userInfo);
        try {
            positionService.save(position);
            return gsonStr(Error.Success);
        } catch (Exception e) {
            logger.error("自定义保存位置异常");
            e.printStackTrace();
            return gsonStr(Error.Unkonwn);
        }
    }


    @GET
    @Path("/historyByTime")
    @Produces(MediaType.APPLICATION_JSON)
    public String queryPositionByTime(
            @QueryParam("u_id") final String uid,
            @QueryParam("time") final String time
    ) {

        Integer u_id = 0;
        TUserInfo userInfo;
        Long longTime;
        List<TServicePosition> positions;
        try {
            u_id = Integer.parseInt(uid);
            userInfo = userInfoService.findById(u_id);
            longTime = Long.parseLong(time);
            if (userInfo == null) {
                logger.error("用户不存在，无法查询位置信息");
                return gsonStr(Error.NotFond);
            }

        } catch (Exception e) {
            logger.error("查询位置异常");
            return gsonStr(Error.TypeError);

        }

        try {
            positions = positionService.findPositionByTime(userInfo, longTime);
            List<Map<String, String>> lists = new ArrayList<>();
            for (TServicePosition p : positions) {
                Map<String, String> map = new HashedMap();
                map.put("position", p.getPosition());
                map.put("time", p.getTime() + "");
                map.put("u_id", p.getUserInfoId().getUId() + "");
                map.put("username", p.getUserInfoId().getName());
                map.put("device_id", p.getUserInfoId().getDeviceId());
                lists.add(map);
            }
            return gsonObj(Error.Success, lists);
        } catch (Exception e) {

            return gsonStr(Error.Unkonwn);
        }


    }

}
